//******************************************************************
//******************************************************************
//**********          ANts Peer To Peer Sources        *************
//
// ANts P2P realizes a third generation P2P net. It protects your
// privacy while you are connected and makes you not trackable, hiding
// your identity (ip) and crypting everything you are sending/receiving
// from others.

// Copyright (C) 2004  Roberto Rossi

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

package ants.p2p.query;

import javax.crypto.*;
import java.io.*;
import ants.p2p.utils.indexer.*;

public class QueryPartialFileTuple extends QueryFileTuple {
  Object fileName;
  Object fileHash;
  Object ed2kFileHash;
  Object chunkHashes;
  Object fileLength;
  Object blockSize;
  Object blocksPerSource;
  Object downloadedBlockGroups;
  Object ownerID;
  Object ownerIP;
  Object freeSlots;
  Object connectionType;
  Object percentage;
  Object extendedInfos;

  public QueryPartialFileTuple(String sessionKey, String fileName, String fileHash, String ed2kFileHash, Object[] chunkHashes, Long fileLength, Integer blockSize, Integer blocksPerSource, boolean[] downloadedBlockGroups, String ownerID, String ownerIP, Integer freeSlots, String connectionType, String percentage, String extendedInfos) {
    super(sessionKey);
    this.fileHash=fileHash;
    this.ed2kFileHash=ed2kFileHash;
    this.chunkHashes=new ChunkHashes(chunkHashes);
    this.fileName=fileName;
    this.fileLength=fileLength;
    this.blockSize=blockSize;
    this.blocksPerSource=blocksPerSource;
    this.downloadedBlockGroups=new DownloadedBlockGroups(downloadedBlockGroups);
    this.ownerID=ownerID;
    this.ownerIP=ownerIP;
    this.freeSlots=freeSlots;
    this.percentage=percentage;
    //this.connectionType=connectionType;
    this.connectionType="Masked";
    this.extendedInfos=extendedInfos;
  }

  public String getFileName() {
    if (this.fileName instanceof String)
      return (String)this.fileName;
    else
      return null;
  }

  public String getFileHash() {
    if (this.fileHash instanceof String)
      return (String)this.fileHash;
    else
      return null;
  }

  public String getED2KFileHash() {
    if (this.ed2kFileHash instanceof String)
      return (String)this.ed2kFileHash;
    else
      return null;
  }

  public ChunkHashes getChunkHashes(){
    if (this.chunkHashes instanceof ChunkHashes)
      return (ChunkHashes)this.chunkHashes;
    else
      return null;
  }

  public Long getSize() {
    if (this.fileLength instanceof Long)
      return (Long)this.fileLength;
    else
      return null;
  }

  public String getOwnerID() {
    if (this.ownerID instanceof String)
      return (String)this.ownerID;
    else
      return null;
  }

  public String getOwnerIP() {
    if (this.ownerID instanceof String)
      return (String)this.ownerIP;
    else
      return null;
  }

  public Integer getFreeSlots() {
    if (this.freeSlots instanceof Integer)
      return (Integer)this.freeSlots;
    else
      return null;
  }

  public String getConnectionType(){
    if(this.connectionType instanceof String)
      return (String)this.connectionType;
    else
      return null;
  }

  public Integer getBlockSize() {
    if (this.blockSize instanceof Integer)
      return (Integer)this.blockSize;
    else
      return null;
  }

  public Integer getBlocksPerSource() {
    if (this.blocksPerSource instanceof Integer)
      return (Integer)this.blocksPerSource;
    else
      return null;
  }

  public boolean[] getDownloadedBlockGroups() {
    if (this.downloadedBlockGroups instanceof DownloadedBlockGroups)
      return ((DownloadedBlockGroups)this.downloadedBlockGroups).downloadedBlockGroups;
    else
      return null;
  }

  public String getPercentage(){
    if(this.percentage instanceof String)
      return (String)this.percentage;
    else
      return null;
  }

  public String getExtendedInfos(){
    if(this.extendedInfos instanceof String)
      return (String)this.extendedInfos;
    else
      return null;
  }

  public void encrypt(Cipher c) throws Exception{
    this.fileName = new SealedObject((String)this.fileName, c);
    this.fileHash = new SealedObject((String)this.fileHash, c);
    this.ed2kFileHash = new SealedObject((String)this.ed2kFileHash, c);
    this.chunkHashes = new SealedObject((ChunkHashes)this.chunkHashes, c);
    this.fileLength = new SealedObject((Long)this.fileLength, c);
    //this.ownerID = new SealedObject((String)this.ownerID, c);
    //this.ownerIP = new SealedObject((String)this.ownerIP, c);
    this.blockSize = new SealedObject((Integer)this.blockSize, c);
    this.blocksPerSource = new SealedObject((Integer)this.blocksPerSource, c);
    this.downloadedBlockGroups = new SealedObject((DownloadedBlockGroups)this.downloadedBlockGroups, c);
    this.freeSlots = new SealedObject((Integer)this.freeSlots, c);
    this.connectionType = new SealedObject( (String)this.connectionType, c);
    this.percentage = new SealedObject((String)this.percentage, c);
    this.extendedInfos = new SealedObject((String)this.extendedInfos, c);
  }

  public void decrypt(Cipher c) throws Exception{
    this.fileName = (String)((SealedObject)this.fileName).getObject(c);
    this.fileHash = (String)((SealedObject)this.fileHash).getObject(c);
    this.ed2kFileHash = (String)((SealedObject)this.ed2kFileHash).getObject(c);
    this.chunkHashes = (ChunkHashes)((SealedObject)this.chunkHashes).getObject(c);
    this.fileLength = (Long)((SealedObject)this.fileLength).getObject(c);
    //this.ownerID = (String)((SealedObject)this.ownerID).getObject(c);
    //this.ownerIP = (String)((SealedObject)this.ownerIP).getObject(c);
    this.blockSize = (Integer)((SealedObject)this.blockSize).getObject(c);
    this.blocksPerSource = (Integer)((SealedObject)this.blocksPerSource).getObject(c);
    this.downloadedBlockGroups = (DownloadedBlockGroups)((SealedObject)this.downloadedBlockGroups).getObject(c);
    this.freeSlots = (Integer)((SealedObject)this.freeSlots).getObject(c);
    this.connectionType = (String) ( (SealedObject)this.connectionType).getObject(c);
    this.percentage = (String)((SealedObject)this.percentage).getObject(c);
    this.extendedInfos = (String)((SealedObject)this.extendedInfos).getObject(c);
  }

  public boolean equals(Object o){
    if(o instanceof FileTupleGroup){
      return ((FileTupleGroup)o).getHash().equals(this.getFileHash())&&
          ((FileTupleGroup)o).getSize().longValue()==this.getSize().longValue();
    }else if(o instanceof QueryCompletedFileTuple){
      return ((QueryCompletedFileTuple)o).getFileHash().equals(this.getFileHash())&&
          ((QueryCompletedFileTuple)o).getSize().longValue()==this.getSize().longValue()&&
          ((QueryCompletedFileTuple)o).getOwnerID().equals(this.getOwnerID());
    }else if (o instanceof QueryPartialFileTuple){
      return ((QueryPartialFileTuple)o).getFileHash().equals(this.getFileHash())&&
          ((QueryPartialFileTuple)o).getSize().longValue()==this.getSize().longValue()&&
          ((QueryPartialFileTuple)o).getOwnerID().equals(this.getOwnerID());
    }else if (o instanceof QueryRemoteFileTuple){
      return ((QueryRemoteFileTuple)o).getFileHash().equals(this.getFileHash())&&
          ((QueryRemoteFileTuple)o).getSize().longValue()==this.getSize().longValue()&&
          ((QueryRemoteFileTuple)o).getOwnerID().equals(this.getOwnerID());
    }else{
      return o==this;
    }
  }

  public String toString(){
    String result = ji.JI.i("Owner ID")+ ": " +
        (this.getOwnerIP().equals("") ? this.getOwnerID().substring(0,10) : this.getOwnerIP())
        + "   "+ji.JI.i("Free Slots")+": ";
    String freeSlots = this.getFreeSlots()+"";
    while(freeSlots.length() < 10)
      freeSlots += " ";
    result += freeSlots;
    String perc = "["+this.getPercentage()+"]";
    while(perc.length() < 6)
      perc+=" ";
    result += perc + "  " + this.getFileName();
    return result;
  }

  public boolean checkHashesValidity(){
    if(this.getChunkHashes().getChunkHashes() == null)
      return true;
    DigestManager dm = new DigestManager();
    try{
      String computedHash = dm.getDigest(this.getChunkHashes().getChunkHashes());
      if(computedHash.equals(this.getFileHash()))
        return true;
      else
        return false;
    }catch(Exception e){
      e.printStackTrace();
      return false;
    }
  }
}

class DownloadedBlockGroups implements Serializable{
  boolean[] downloadedBlockGroups;

  public DownloadedBlockGroups(boolean[] downloadedBlockGroups){
    this.downloadedBlockGroups = downloadedBlockGroups;
  }

  public boolean[] getDownloadedBlockGroups(){
    return this.downloadedBlockGroups;
  }
}
